from datetime import datetime
from decimal import Decimal
from django.db import transaction
from django.utils import timezone
from django_redis import get_redis_connection
from rest_framework import serializers

from goods.models import SKU
from meiduo.utils.exceptions import logger
from orders.models import OrderInfo, OrderGoods


class CartSKUSerializer(serializers.ModelSerializer):
    """
    购物车商品数据序列化器
    """
    count = serializers.IntegerField(label='数量', min_value=1)

    class Meta:
        model = SKU
        fields = '__all__'


class OrderSettlementSerializer(serializers.Serializer):
    """
    订单结算数据序列化器
    """
    freight = serializers.DecimalField(label='运费', max_digits=10, decimal_places=2)
    skus = CartSKUSerializer(many=True)


# class SaveOrderSerializer(serializers.ModelSerializer):
#     """
#     下单数据序列化器
#     """
#     class Meta:
#         model = OrderInfo
#         fields = ('order_id', 'address', 'pay_method')
#         read_only_fields = ('order_id')
#         extra_kwargs = {
#             'address': {
#                 'write_only': True,
#                 'required': True,
#             },
#             'pay_method': {
#                 'write_only': True,
#                 'required': True
#             }
#         }
#
#     # @transaction.atomic()
#     def create(self, validated_data):
#         """
#         保存订单
#         :param validated_data:
#         :return:
#         """
#         # 获取当前下单用户
#         user = self.context['request'].user
#
#         # 获取收货地址
#         address = validated_data['address']
#         pay_method = validated_data['pay_method']
#
#         # 组织订单编号 20170903153611+user.id
#         # timezone.now() -> datetime
#         # order_id = timezone.now().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id)
#         order_id = datetime.now().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id)
#
#         # 生成订单(事务）
#         with transaction.atomic():
#             # 创建一个保存点
#             save_id = transaction.savepoint()
#
#             try:
#                 # 创建订单信息
#                 order = OrderInfo.objects.create(
#                     order_id=order_id,
#                     user=user,
#                     address=address,
#                     total_count=0,
#                     total_amount=Decimal(0),
#                     freight=Decimal(10),
#                     pay_method=pay_method,
#                     status=OrderInfo.ORDER_STATUS_ENUM['UNSEND'] if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH'] else OrderInfo.ORDER_STATUS_ENUM['UNPAID']
#                 )
#                 # 获取购物车信息
#                 redis_conn = get_redis_connection("cart")
#                 sku_id_count = redis_conn.hgetall("cart_%s" % user.id)
#                 cart_selected = redis_conn.smembers('cart_selected_%s' % user.id)
#
#                 # 将bytes类型转换为int类型
#                 cart = {}
#                 for sku_id in cart_selected:
#                     cart[int(sku_id)] = int(sku_id_count[sku_id])
#
#                 # 一次查询出所有商品数据
#                 # skus = SKU.objects.filter(id__in=cart.keys())
#
#                 # 处理订单商品
#                 sku_id_list = cart.keys()
#                 for sku in sku_id_list:
#                     while True:
#                         # 逐个查询数据
#                         sku = SKU.objects.get(sku.id)
#
#                         cart_count = cart[sku.id]  # 获取购买数量
#
#                         # 判断库存
#                         origin_stock = sku.stock  # 原始库存
#                         origin_sales = sku.sales  # 原始销量
#
#                         if cart_count > origin_stock:
#                             transaction.savepoint_rollback(save_id)
#                             raise serializers.ValidationError('商品库存不足')
#
#                             # 用于演示并发下单
#                             # import time
#                             # time.sleep(5)
#
#                             # 减少库存
#                             # sku.stock -= sku_count
#                             # sku.sales += sku_count
#                             # sku.save()
#                         new_stock = origin_stock - cart_count
#                         new_sales = origin_sales + cart_count
#
#                         # sku.stock = new_stock
#                         # sku.sales = new_sales
#                         # sku.save()
#
#                         # 根据原始库存条件更新，返回更新的条目数，乐观锁
#
#                         ret = SKU.objects.filter(id=sku.id, stock=origin_stock).update(stock=new_stock, sales=new_sales)
#                         if ret == 0:
#                             continue
#
#                         # 累计商品的SPU 销量信息
#                         sku.goods.sales += cart_count
#                         sku.goods.save()
#
#                         # 累计订单基本信息的数据
#                         order.total_count += cart_count  # 累计总金额
#                         order.total_amount += (sku.price * cart_count)  # 累计总额
#                         order.save()
#
#                         # 保存订单商品
#                         OrderGoods.objects.create(
#                             order=order,
#                             sku=sku,
#                             count=cart_count,
#                             price=sku.price,
#                         )
#
#                         # 更新成功
#                         break
#
#                 # 更新订单的金额数量信息
#                 order.total_amount += order.freight
#                 order.save()
#
#             except:
#                 transaction.savepoint_rollback(save_id)
#
#             else:
#
#                 # 提交事务
#                 transaction.savepoint_commit(save_id)
#
#                 # 更新redis中保存的购物车数据
#                 pl = redis_conn.pipeline()
#                 pl.hdel('cart_%s' % user.id, *cart_selected)
#                 pl.srem('cart_selected_%s' % user.id, *cart_selected)
#                 pl.execute()
#                 return order


class SaveOrderSerializer(serializers.ModelSerializer):

    class Meta:
        model = OrderInfo
        fields = ('order_id', 'pay_method', 'address')
        read_only_fields = ('order_id',)
        extra_kwargs = {
            'pay_method': {
                'write_only': True,
                'required': True
            },
            'address': {
                'write_only': True,
                'required': True
            }
        }

    # @transaction.atomic()
    def create(self, validated_data):

        # 获取当前用户
        user = self.context['request'].user

        # 获取支付方式和收货地址
        pay_method = validated_data['pay_method']
        address = validated_data['address']

        # 生成订单编号
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + '%09d' % user.id

        with transaction.atomic():
            # 生成一个保存点
            save_point = transaction.savepoint()
            print(1111)
            try:
                # 创建生成订单基本信息表对象
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    total_count=0,
                    total_amount=Decimal(0),
                    freight=Decimal(10),
                    pay_method=pay_method,
                    status=OrderInfo.ORDER_STATUS_ENUM['UNSEND'] if pay_method == OrderInfo.PAY_METHODS_ENUM[
                        'CASH'] else OrderInfo.ORDER_STATUS_ENUM['UNPAID']

                )

                # 查询订单商品

                # 获取缓存数据
                conn = get_redis_connection('cart')
                # 获取sku_id和count
                sku_id_count = conn.hgetall('cart_%s' % user.id)
                # 获取选中状态
                cart_selected = conn.smembers('cart_selected_%s' % user.id)

                # 构建数据
                cart = {}
                for sku_id in cart_selected:
                    cart[int(sku_id)] = int(sku_id_count[sku_id])

                # 数据查询
                # skus = SKU.objects.filter(id__in=cart.keys())

                # 循环遍历 修改商品数据
                for sku_id in cart.keys():

                    while True:
                        # 一个一个的查询数据
                        sku=SKU.objects.get(id=sku_id)

                        cart_count = int(cart[sku.id])  # 获取购买数量

                        old_stock = sku.stock  # 原始库存
                        old_sales = sku.sales  # 原始销量

                        # 判断库存是否充足
                        if cart_count > old_stock:
                            raise serializers.ValidationError('库存不足')



                        # 修改库存和销量
                        new_stock = old_stock - cart_count
                        new_sales = old_sales + cart_count

                        # sku.stock = new_stock
                        # sku.sales = new_sales
                        # sku.save()
                        # 数据更新之前再次进行查询库存
                        ret=SKU.objects.filter(id=sku.id, stock=old_stock).update(stock=new_stock, sales=new_sales)
                        if ret == 0:
                            continue


                        # 修改spu表总销量
                        sku.goods.sales += cart_count
                        sku.goods.save()

                        # 修改order表中总量和总价
                        order.total_count += cart_count
                        order.total_amount += (sku.price * cart_count)
                        order.save()
                        # 创建商品订单表
                        OrderGoods.objects.create(
                            order=order,
                            sku=sku,
                            count=cart_count,
                            price=sku.price,

                        )
                        break

                # 总价加运费
                order.total_amount+=order.freight
                order.save()

            except:
                transaction.savepoint_rollback(save_point)
            else:

                transaction.savepoint_commit(save_point)
                # 删除缓存中选中状态的商品
                conn.hdel('cart_%s'%user.id,*cart_selected)
                conn.srem('cart_selected_%s'%user.id,*cart_selected)

                # 返回订单对象
                return order